home *** CD-ROM | disk | FTP | other *** search
-
- static char RCSId[]="$Id: FunctionObject.m,v 1.1.1.1 1993/03/18 03:33:14 davis Exp $";
-
-
- #import "FunctionObject.h"
-
- #import <sys/stat.h> /* stat() */
- #import <sys/types.h> /* stat() */
-
- #import <objc/hashtable.h> /* NXCopyStringBufferFromZone() */
- #import <objc/zone.h>
-
- #import <ctype.h> /* isspace() */
- #import <libc.h> /* index(), rindex() */
-
-
- const char *styleString[] = {"lines", "points", "linespoints", "dots",
- "impulses", "errorbars", "boxes", "boxerrorbars"};
-
-
- /* Is the string blank (i.e. full of only white space)? */
- static BOOL _isBlank (const char *aString)
- {
- const char *cur;
-
- for (cur = aString ; *cur != '\0' ; cur++)
- if (*cur != ' ' && *cur != '\t' && *cur != '\n')
- return NO;
-
- return YES;
- }
-
-
- static BOOL _isSpaceNotNL (char aChar)
- {
- return (isspace (aChar)) && (aChar != '\n');
- }
-
-
-
-
- /*
- * aString is assumed to be a one-line string (i.e it contains no
- * newlines). This could be changed easily if need be.
- */
- static void _removeComments (char *aString)
- {
- char *cur = aString;
- char quote[100];
- int number = 0;
-
- while (*cur) {
- if ((*cur == '\'') || (*cur == '"')) {
-
- /*
- * The quote is either closing a previous quotation or
- * starting a new one. We look at the last quote
- * encountered to see which.
- */
- if (number && (*cur == quote[number - 1])) /* closing previous */
- number--;
- else /* starting new */
- quote[number++] = *cur;
-
- } else if (number && (*cur == '#')) {
-
- /*
- * If we've encountered a pound sign outside of a
- * quotation, we've found a comment. The rest of the
- * line can be truncated.
- */
- cur = '\0';
-
- }
-
- cur++;
- }
-
- }
-
-
- static void _getWith (char *aString, int *style, int *lineStyle,
- int *pointsStyle)
- {
- char *cur, *with;
-
- /*
- * This attempts to detect a 'with' phrase and to extract the
- * style from it if it exists. There are several ways to trick
- * this.
- */
- if ((with = rindex (aString, 'w')) && (*(with+1) == 'i') &&
- (cur = index (with, ' '))) {
- switch (*(++cur)) {
- case 'p': *style = FUNCTION_POINTS; break;
- case 'd': *style = FUNCTION_DOTS; break;
- case 'i': *style = FUNCTION_IMPULSES; break;
- case 'e': *style = FUNCTION_ERRORBARS; break;
- case 'b':
- if (index (cur, 'r')) *style = FUNCTION_BOXERRORBARS;
- else *style = FUNCTION_BOXES;
- break;
- case 'l':
- if (index (cur, 'p')) *style = FUNCTION_LINESPOINTS;
- else *style = FUNCTION_LINES;
- break;
- default: *style = FUNCTION_NOSTYLE; break;
- }
- *with = '\0';
-
- /*
- * If the style type includes lines or points, the user has
- * the option of setting the point/line styles. Check for
- * those...
- */
- /* Line Style */
- if ((*style == FUNCTION_POINTS) || (*style == FUNCTION_LINES) ||
- (*style == FUNCTION_LINESPOINTS)) {
-
- while (cur && *cur && ((*cur > '6') || (*cur < '1')))
- cur++;
- if (cur && *cur)
- *lineStyle = *cur - '0';
-
- /* Point Style */
- if ((*style == FUNCTION_POINTS) ||
- (*style == FUNCTION_LINESPOINTS)) {
-
- while (cur && *cur && ((*cur > '6') || (*cur < '1')))
- cur++;
- if (cur && *cur)
- *pointsStyle = *cur - '0';
- }
-
- }
-
- }
-
- }
-
-
-
-
- static char *_getTitle (char *aString)
- {
- while (aString && *aString) {
-
- /*
- * If this appears to be a "title" phrase, see if a quoted
- * string follows. If one does, chop it off and return it.
- */
-
- if ((*aString == 't') &&
- ((*(aString + 1) == 'i') || _isSpaceNotNL (*(aString + 1)))) {
-
- char *firstQuote, *beginning = aString;
-
- while (!_isSpaceNotNL (*aString))
- aString++;
- while (_isSpaceNotNL (*aString))
- aString++;
- if ((*aString == '\'') || (*aString == '"')) {
-
- /*
- * Okay, we are as sure as can be that this is a
- * "title" phrase.
- */
- firstQuote = aString;
- if (aString = index (++aString, *firstQuote))
- *aString = '\0';
- *beginning = '\0';
-
- return ++firstQuote;
- }
-
- }
-
- aString++;
- }
-
- return NULL;
- }
-
-
- @implementation FunctionObject
-
-
- /* Does the string contain something besides white space? */
- + (BOOL) isAcceptableStringValue:(const char *)aString
- {
- return (aString && !_isBlank (aString));
- /* todo, also check for valid functions, if possible */
- }
-
-
- /*
- * Makes sure the file whose full path is specified by aString is a
- * regular, readable file.
- */
- + (BOOL) isAcceptableDataFile:(const char *)aString
- {
- struct stat fileinfo;
- BOOL returnVal;
-
- returnVal = (aString && !stat (aString, &fileinfo) &&
- ((fileinfo.st_mode & S_IFMT) == S_IFREG) &&
- (fileinfo.st_mode & S_IREAD));
- return returnVal;
- }
-
-
-
- /*
- * The attributes of a function are stored by an instance of
- * FunctionObject. The only complicated part is parsing those
- * attributes from a Gnuplot "plot" statement. aString should
- * specify only the part of that statement pertaining to the function
- * that will be stored by this instance and should contain no leading
- * white space. (This method could be nicer by ignoring leading
- * white space.)
- */
- - initFromString:(const char *)aString
- {
- char quote, *cur;
- NXZone *zone;
-
- [super init];
-
- zone = [self zone];
-
- title = NULL; /* Defaults */
- style = FUNCTION_NOSTYLE;
- pointsStyle = POINTS_NOSTYLE;
- lineStyle = LINE_NOSTYLE;
- isDataFile = NO;
-
- if (aString) {
-
- stringValue = NXCopyStringBufferFromZone (aString, zone);
- _removeComments (stringValue);
- _getWith (stringValue, &style, &lineStyle, &pointsStyle);
- [self setTitle:_getTitle (stringValue)];
-
- /*
- * If this string value is quoted, it is a data file. We
- * remove the quotes and set the isDataFile flag. The string
- * is assumed to have no leading white space, i.e. if it is a
- * data file, the first character is a quote.
- */
-
- quote = *stringValue;
- if ((quote == '\'') || (quote == '"')) { /* This is a data file */
-
- isDataFile = YES;
- *rindex (stringValue, quote) = '\0';
- cur = NXCopyStringBufferFromZone (stringValue+1, zone);
- NXZoneFree (zone, stringValue);
- stringValue = cur;
-
- } else { /* This is a function, not a data file. */
-
- /* Remove trailing blanks */
- cur = stringValue + strlen (stringValue) - 1 ;
- while (isspace (*cur) && (cur >= stringValue))
- *(cur--) = '\0';
-
- }
-
- } else
- stringValue = NULL;
-
- return self;
- }
-
-
- - free
- {
- NXZoneFree ([self zone], title);
-
- return [super free];
- }
-
-
- - setDataFile:(BOOL)cond
- {
- isDataFile = cond;
- return self;
- }
-
-
- - (BOOL)isDataFile
- {
- return isDataFile;
- }
-
-
- - setTitle:(const char *)aString
- {
- char *aux;
- NXZone *zone = [self zone];
-
- NXZoneFree (zone, title);
- if (aString) {
-
- title = NXCopyStringBufferFromZone (aString, zone);
-
- /*
- * Make sure aString doesn't mix both kinds of quotation marks.
- * Gnuplot can handle one or the other but not both in one title.
- * (If there's a mix, use double quotation marks.)
- */
-
- if ( (index (title, '"')) && (aux = index (title, '\'')) ) {
- do
- *aux = '"';
- while (aux = index (title, '\''));
- }
-
- } else
- title = NULL;
-
- return self;
- }
-
-
- - (const char *)title
- {
- return title;
- }
-
-
- - setStyle:(int) anInt
- {
- style = anInt;
- return self;
- }
-
-
- - (int)style
- {
- return style;
- }
-
-
- - (const char *)styleString
- {
- if (style == FUNCTION_NOSTYLE)
- return NULL;
- else
- return styleString[style];
- }
-
-
- - setPointsStyle: (int)anInt
- {
- pointsStyle = anInt;
- return self;
- }
-
-
- - (int)pointsStyle
- {
- return pointsStyle;
- }
-
-
- - setLineStyle: (int)anInt
- {
- lineStyle = anInt;
- return self;
- }
-
-
- - (int)lineStyle
- {
- return lineStyle;
- }
-
-
-
- /*
- * If the function is actually a data file, it is similar to an
- * attachment, or a "file link," so we return YES. If the function
- * is not a data file, we return NO.
- */
- - (BOOL)isAttachment
- {
- return isDataFile;
- }
-
-
- // Shuts up the compiler about unused RCSId
- - (const char *) rcsid
- {
- return RCSId;
- }
-
-
- @end
-